package com.information.service;

import com.information.entity.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.shyiko.mysql.binlog.BinaryLogClient;
import com.github.shyiko.mysql.binlog.event.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.Serializable;
import java.util.Map;

@Service
public class BinlogListenerService {

    @Autowired
    private RedisService redisService;

    @Autowired
    private ObjectMapper objectMapper;

    private String datasourceUrl = "jdbc:mysql://localhost:3306/user_management?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true&autoReconnect=true";

    private String username = "binlog_user";

    private String password = "WTT713";

    private BinaryLogClient client;
    private String usersTableName = "users";

    @PostConstruct
    public void startListening() {
        try {
            // 从数据源URL解析主机和端口
            String host = extractHost(datasourceUrl);
            int port = extractPort(datasourceUrl);

            client = new BinaryLogClient(host, port, username, password);
            client.setServerId(1001); // 设置唯一的服务器ID

            client.registerEventListener(event -> {
                EventData data = event.getData();

                if (data instanceof TableMapEventData) {
                    // 记录表映射信息
                    handleTableMapEvent((TableMapEventData) data);
                } else if (data instanceof WriteRowsEventData) {
                    // INSERT操作
                    handleInsertEvent((WriteRowsEventData) data);
                } else if (data instanceof UpdateRowsEventData) {
                    // UPDATE操作
                    handleUpdateEvent((UpdateRowsEventData) data);
                } else if (data instanceof DeleteRowsEventData) {
                    // DELETE操作
                    handleDeleteEvent((DeleteRowsEventData) data);
                }
            });

            // 异步启动监听
            new Thread(() -> {
                try {
                    client.connect();
                } catch (Exception e) {
                    System.err.println("启动Binlog监听失败: " + e.getMessage());
                }
            }).start();

        } catch (Exception e) {
            System.err.println("初始化Binlog监听失败: " + e.getMessage());
        }
    }

    private void handleTableMapEvent(TableMapEventData data) {
        // 可以在这里记录表结构信息
    }

    private void handleInsertEvent(WriteRowsEventData data) {
        if (isUsersTable(data.getTableId())) {
            for (Serializable[] row : data.getRows()) {
                try {
                    User user = parseUserFromRow(row);
                    if (user != null) {
                        // 缓存新插入的用户
                        redisService.cacheUser(user);
                        redisService.cacheUserByUsername(user);
                        redisService.evictAllUsers(); // 清除用户列表缓存
                    }
                } catch (Exception e) {
                    System.err.println("处理INSERT事件失败: " + e.getMessage());
                }
            }
        }
    }

    private void handleUpdateEvent(UpdateRowsEventData data) {
        if (isUsersTable(data.getTableId())) {
            for (Map.Entry<Serializable[], Serializable[]> entry : data.getRows()) {
                try {
                    Serializable[] oldRow = entry.getKey();
                    Serializable[] newRow = entry.getValue();

                    User oldUser = parseUserFromRow(oldRow);
                    User newUser = parseUserFromRow(newRow);

                    if (oldUser != null && newUser != null) {
                        // 如果用户被软删除，清除缓存而不是更新
                        if (newUser.getIsDelete()) {
                            redisService.evictUser(newUser.getId());
                            redisService.evictUserByUsername(newUser.getUsername());
                            redisService.evictAllUsers();
                        } else {
                            // 更新缓存
                            redisService.cacheUser(newUser);
                            redisService.cacheUserByUsername(newUser);

                            // 如果用户名发生变化，清除旧用户名缓存
                            if (!oldUser.getUsername().equals(newUser.getUsername())) {
                                redisService.evictUserByUsername(oldUser.getUsername());
                            }

                            redisService.evictAllUsers();
                        }
                    }
                } catch (Exception e) {
                    System.err.println("处理UPDATE事件失败: " + e.getMessage());
                }
            }
        }
    }

    private void handleDeleteEvent(DeleteRowsEventData data) {
        if (isUsersTable(data.getTableId())) {
            for (Serializable[] row : data.getRows()) {
                try {
                    User user = parseUserFromRow(row);
                    if (user != null) {
                        // 清除缓存
                        redisService.evictUser(user.getId());
                        redisService.evictUserByUsername(user.getUsername());
                        redisService.evictAllUsers(); // 清除用户列表缓存
                    }
                } catch (Exception e) {
                    System.err.println("处理DELETE事件失败: " + e.getMessage());
                }
            }
        }
    }

    private User parseUserFromRow(Serializable[] row) {
        try {
            if (row.length >= 14) { // 更新为14列（新增3个字段）
                User user = new User();
                user.setId(row[0] != null ? ((Number) row[0]).longValue() : null);
                user.setUsername(row[1] != null ? row[1].toString() : null);
                user.setPassword(row[2] != null ? row[2].toString() : null);
                user.setName(row[3] != null ? row[3].toString() : null);
                user.setEmail(row[4] != null ? row[4].toString() : null);
                user.setPhone(row[5] != null ? row[5].toString() : null);
                user.setAge(row[6] != null ? ((Number) row[6]).intValue() : null);
                user.setGender(row[7] != null ? row[7].toString() : null);
                user.setAddress(row[8] != null ? row[8].toString() : null);

                if (row[9] != null) {
                    user.setRole(User.UserRole.valueOf(row[9].toString()));
                }
                user.setIsDelete(row[10] != null ? ((Number) row[10]).intValue() == 1 : false);
                if (row[11] != null) {
                    user.setStatus(User.UserStatus.valueOf(row[11].toString()));
                }

                // row[12] 和 row[13] 是 created_at 和 updated_at
                return user;
            }
        } catch (Exception e) {
            System.err.println("解析用户数据失败: " + e.getMessage());
        }
        return null;
    }

    private boolean isUsersTable(long tableId) {
        // 简化实现，实际应该维护tableId到表名的映射
        return true; // 这里需要根据实际情况判断
    }

    private String extractHost(String url) {
        // 从 jdbc:mysql://localhost:3306/user_management 提取 localhost
        String[] parts = url.split("//")[1].split("/")[0].split(":");
        return parts[0];
    }

    private int extractPort(String url) {
        // 从 jdbc:mysql://localhost:3306/user_management 提取 3306
        String[] parts = url.split("//")[1].split("/")[0].split(":");
        return parts.length > 1 ? Integer.parseInt(parts[1]) : 3306;
    }

    @PreDestroy
    public void stopListening() {
        if (client != null) {
            try {
                client.disconnect();
            } catch (Exception e) {
                System.err.println("停止Binlog监听失败: " + e.getMessage());
            }
        }
    }
}